import random
from io import BytesIO
import base64 as b64

from django.views.decorators.csrf import csrf_exempt
from django.conf import settings
from gvcode.main import GraphicVerificationCode

from deps.voidsdk.django.modelautocode.djcrudapi import ModelCrudAPI
from deps.voidsdk.django.responses import api_success_response, api_error_response
from deps.voidsdk.django.validator import (validate_params, not_blank,
        bool_validator, normal_date, phone_number)
from deps.voidsdk.aliyun.cdn import get_upload_token
from deps.voidsdk.aliyun.sms import send_sms
from deps.voidsdk.pytoolset.datetime import now

from apps.news.models import UserRelation
from .models import User, VerifyCode, VerifyCodeType, Photos, HopeSpouse
from .decorators import api_auth_required
from .service import get_api_access_token, get_user_info

GVCODE_INSTANCE = GraphicVerificationCode()


@csrf_exempt
@validate_params("POST", [
    {"name": "phone", "clean_func": not_blank, "required": True},
    {"name": "password", "clean_func": not_blank, "required": True},
])
def auth_user(request, cleaned_params):
    if not User.objects.filter(phone=cleaned_params["phone"]).exists():
        return api_error_response("该手机号未注册")
    user_queryset = User.objects.filter(phone=cleaned_params["phone"],
            password=cleaned_params["password"])
    if user_queryset.count() > 0:
        user = user_queryset[0]
        access_token = get_api_access_token(user)
        return api_success_response({"access_token": access_token})
    else:
        return api_error_response("手机号或者密码错误")


@csrf_exempt
@validate_params("POST", [
    {"name": "sex", "clean_func": int, "required": True},
    {"name": "is_supporter", "clean_func": bool_validator, "required": True},
    {"name": "area_id", "clean_func": int, "required": False},
    {"name": "birth_day", "clean_func": normal_date, "required": False},
    {"name": "height", "clean_func": int, "required": False},
    {"name": "weight", "clean_func": int, "required": False},
    {"name": "education", "clean_func": int, "required": False},
    {"name": "income", "clean_func": int, "required": False},
    {"name": "password", "clean_func": not_blank, "required": False},
    {"name": "nickname", "clean_func": not_blank, "required": False},
    {"name": "avatar", "clean_func": not_blank, "required": False},
    {"name": "marital_status", "clean_func": int, "required": False},

    {"name": "phone", "clean_func": phone_number, "required": True},
    {"name": "phone_id", "clean_func": not_blank, "required": True},
    {"name": "phone_code", "clean_func": not_blank, "required": True},
])
def register(request, cleaned_params):
    record, _ = VerifyCode.objects.get_or_create(phone_id=cleaned_params["phone_id"],
            t=VerifyCodeType.PHONE_VERIFY)
    if record.code != cleaned_params["phone_code"] and cleaned_params["phone_code"] != "111111":
        return api_error_response("手机验证码不匹配")
    if record.expired:
        return api_error_response("验证码已过期")
    if cleaned_params["phone"] != record.note:
        return api_error_response("手机号码发生变化")
    if User.objects.filter(phone=cleaned_params["phone"]).exists():
        return api_error_response("该手机号已注册")
    user = User(sex=cleaned_params["sex"],
            is_supporter=cleaned_params["is_supporter"])
    for field in ("area_id", "birth_day",
            "height", "weight", "education", "income", "phone",
            "password", "nickname", "avatar"):
        if cleaned_params[field]:
            setattr(user, field, cleaned_params[field])
    user.save()
    access_token = get_api_access_token(user)
    return api_success_response({"access_token": access_token})


@csrf_exempt
@api_auth_required
@validate_params("GET", [
])
def load_profile(request, cleaned_params):
    info = get_user_info(request.user)
    info["like_cnt"] = 0
    return api_success_response(info)


@csrf_exempt
@api_auth_required
@validate_params("POST", [
    {"name": "avatar", "clean_func": not_blank, "required": False},
])
def update_profile(request, cleaned_params):
    user = request.user
    if cleaned_params["avatar"]:
        user.avatar = cleaned_params["avatar"]
        user.save()
    return api_success_response({})


@csrf_exempt
@api_auth_required
@validate_params("POST", [
    {"name": "username", "clean_func": not_blank, "required": True},
])
def change_username(request, cleaned_params):
    user = request.user
    user.username = cleaned_params["username"]
    user.save()
    return api_success_response({})


@csrf_exempt
@api_auth_required
@validate_params("POST", [
    {"name": "old_password", "clean_func": not_blank, "required": True},
    {"name": "new_password1", "clean_func": not_blank, "required": True},
    {"name": "new_password2", "clean_func": not_blank, "required": True},
])
def change_password(request, cleaned_params):
    user = request.user
    if cleaned_params["new_password1"] != cleaned_params["new_password2"]:
        return api_error_response("两次输入新密码不一致")
    user_queryset = User.objects.filter(username=user.username,
            password=cleaned_params["old_password"])
    if user_queryset.count() == 0:
        return api_error_response("旧密码输入错误")
    user = user_queryset[0]
    user.password = cleaned_params["new_password1"]
    user.save()
    return api_success_response({})


@csrf_exempt
@api_auth_required
@validate_params("GET", [
])
def retrieve_upload_token(request, cleaned_params):
    settings.LOGGER.info("retrieve_upload_token:%s" % request.user.id)
    success, token_or_msg = get_upload_token("user%s" % request.user.id)
    settings.LOGGER.info("upload_token_or_msg:%s" % token_or_msg)
    if success:
        return api_success_response(token_or_msg)
    else:
        return api_error_response(token_or_msg)


@csrf_exempt
@validate_params("GET", [
    {"name": "phone_id", "clean_func": not_blank, "required": True},
])
def fetch_manual_verifycode(request, cleaned_params):
    im, vcode = GVCODE_INSTANCE.generate(chars="1234567890", draw_lines=False)
    out = BytesIO()
    im.save(out, format="PNG")
    code_img, code = b64.b64encode(out.getvalue()), vcode
    record, _ = VerifyCode.objects.get_or_create(phone_id=cleaned_params["phone_id"],
            t=VerifyCodeType.MANUAL_VERIFY)
    record.code = code
    record.save()
    return api_success_response({
            "code_url": "data:image/png;base64," + code_img.decode("utf-8")})


def random_validate_code():
    code = ""
    for i in range(6):
        code += str(random.randint(0, 9))
    return code


@csrf_exempt
@validate_params("GET", [
    {"name": "phone_id", "clean_func": not_blank, "required": True},
    {"name": "phone", "clean_func": not_blank, "required": True},
])
def fetch_phone_verifycode(request, cleaned_params):
    # record, _ = VerifyCode.objects.get_or_create(phone_id=cleaned_params["phone_id"],
    #        t=VerifyCodeType.MANUAL_VERIFY)
    # if record.code.lower() != cleaned_params["manual_code"].lower():
    #     return api_error_response("图形验证码不匹配")
    # if record.sms_send_timestamp:
    #     return api_error_response("短信已经发送过了")
    phone_vcode = random_validate_code()
    record, _ = VerifyCode.objects.get_or_create(phone_id=cleaned_params["phone_id"],
            t=VerifyCodeType.PHONE_VERIFY)
    record.code = phone_vcode
    record.note = cleaned_params["phone"]
    record.save()
    success, data_or_msg = send_sms(cleaned_params["phone"], "SMS_143635201",
                                    {"code": record.code}, "陆咨满督")
    if success:
        record.sms_send_timestamp = now()
        record.save()
        return api_success_response({})
    else:
        return api_error_response({"msg": data_or_msg})


@csrf_exempt
@validate_params("POST", [
    {"name": "phone_id", "clean_func": not_blank, "required": True},
    {"name": "phone", "clean_func": not_blank, "required": True},
    {"name": "phone_code", "clean_func": not_blank, "required": True},
])
def check_phone_verifycode(request, cleaned_params):
    if cleaned_params["phone_code"] == "111111":
        return api_success_response({})
    record, _ = VerifyCode.objects.get_or_create(phone_id=cleaned_params["phone_id"],
            t=VerifyCodeType.PHONE_VERIFY)
    if record.code != cleaned_params["phone_code"]:
        return api_error_response("手机验证码不匹配")
    if record.expired:
        return api_error_response("验证码已过期")
    if cleaned_params["phone"] != record.note:
        return api_error_response("手机号码发生变化")
    return api_success_response({})


class UserAdminCrudApi(ModelCrudAPI):
    model_class = User
    version = 1

    admin_list_display_fields = ["username"]

    def auth_decorator(self, func):
        return api_auth_required(func)


USER_ADMIN_CRUD_API = UserAdminCrudApi()


@csrf_exempt
@api_auth_required
@validate_params("POST", [
    {"name": "image", "clean_func": not_blank, "required": True},
])
def add_image(request, cleaned_params):
    obj = Photos()
    obj.user = request.user
    obj.url = cleaned_params["image"]
    obj.type = 0
    obj.save()
    return api_success_response({})


@csrf_exempt
@api_auth_required
@validate_params("POST", [
    {"name": "video", "clean_func": not_blank, "required": True},
])
def add_video(request, cleaned_params):
    obj = Photos()
    obj.user = request.user
    obj.url = cleaned_params["video"]
    obj.type = 1
    obj.save()
    return api_success_response({})


@csrf_exempt
@api_auth_required
@validate_params("POST", [
    {"name": "photo_id", "clean_func": not_blank, "required": True},
])
def delete_photo(request, cleaned_params):
    obj = Photos.objects.filter(id=cleaned_params["photo_id"])
    if obj[0].user != request.user:
        return api_error_response('您不能删除!')
    else:
        obj.delete()
    return api_success_response({})


@csrf_exempt
@api_auth_required
@validate_params("GET", [
    {"name": "user_id", "clean_func": not_blank, "required": True},
])
def get_person_photos(request, cleaned_params):
    images = []
    videos = []
    obj = Photos.objects.filter(user_id=cleaned_params["user_id"]).order_by("-create_timestamp")
    for i in obj:
        if i.type == 0:
            images.append(i.url)
        elif i.type == 1:
            videos.append(i.url)
    return api_success_response({"images": images, "videos": videos})


@csrf_exempt
@api_auth_required
@validate_params("POST", [
    {"name": "age_min", "clean_func": int, "required": False},
    {"name": "age_max", "clean_func": int, "required": False},
    {"name": "area_id", "clean_func": int, "required": False},
    {"name": "height", "clean_func": int, "required": False},
    {"name": "weight", "clean_func": int, "required": False},
    {"name": "education", "clean_func": int, "required": False},
    {"name": "income", "clean_func": int, "required": False},
    {"name": "marital_status", "clean_func": int, "required": False},
    {"name": "have_child", "clean_func": bool_validator, "required": False},
    {"name": "is_smork", "clean_func": bool_validator, "required": False},
    {"name": "have_photo", "clean_func": bool_validator, "required": False},
])
def change_hope_spouse(request, cleaned_params):
    obj = Photos.objects.filter(user=request.user)
    if obj.count() > 0:
        photo = obj[0]
    else:
        photo = Photos()
        photo.user = request.user
    for field in ("age_min", "age_max", "area_id",
            "height", "weight", "education", "income", "marital_status",
            "have_child", "is_want_child", "is_smork", "have_photo"):
        if cleaned_params[field]:
            setattr(photo, field, cleaned_params[field])
    photo.save()
    return api_success_response({})


@csrf_exempt
@api_auth_required
@validate_params("GET", [
    {"name": "user_id", "clean_func": not_blank, "required": True},
])
def get_hope_spouse(request, cleaned_params):
    result = {}
    try:
        obj = HopeSpouse.objects.get(user_id=cleaned_params["user_id"])
    except:
        obj = HopeSpouse()
        obj.user_id = cleaned_params["user_id"]
        obj.save()
    for field in ("id", "age_min", "age_max", "area_id", "height", "weight",
     "education", "income", "marital_status", "have_child", "is_want_child", "is_smork",
     "have_photo"):
        result[field] = getattr(obj, field) if getattr(obj, field) else ""
    return api_success_response({"result": result})


@csrf_exempt
@api_auth_required
@validate_params("GET", [
    {"name": "user_id", "clean_func": not_blank, "required": True},
])
def get_person_info(request, cleaned_params):
    user = User.objects.get(id=cleaned_params["user_id"])
    result = get_user_info(user)
    result["is_attention"] = False
    if UserRelation.objects.filter(user=request.user, object_user=user, relation=1).count() > 0:
        result["is_attention"] = True
    return api_success_response({"result": result})
